# -*- coding:utf-8 -*-
# @File    : writeCaseYaml.py
# ****************************
import os
import json
import logging
import urllib.parse
from json import JSONDecodeError

from comm.utils.readYaml import write_yaml_file, read_yaml_data
from comm.utils.readJson import write_json_file, read_json_data
from config import API_CONFIG, PROJECT_NAME,RC


run_evn = RC["run_evn"]
num = RC["case_num"]
def init_api_conf(har_ct):
    host = har_ct["host"]
    port = har_ct["actualPort"]
    headers = har_ct["request"]["header"]['headers']
    # 定义项目api通过配置
    proj_conf = dict()
    proj_conf['timeout'] = 10
    proj_conf['scheme'] = har_ct["scheme"]
    proj_conf['host'] = host + ':' + str(port)
    simp_header = dict()
    for header in headers:
        # 去除基础请求头
        base_header = ['Host',
                       'Content-Length',
                       'User-Agent',
                       'Origin',
                       'Referer',
                       'Connection',
                       'Accept',
                       'Accept-Encoding',
                       'Accept-Language']
        if header['name'] not in base_header:
            simp_header[header['name']] = header['value']

    # 判断是否存在自定义消息头
    if simp_header:
        proj_conf['headers'] = simp_header
    else:
        proj_conf['headers'] = None

    # 检查是否已存在项目配置信息，没有则写入
    run_conf = read_yaml_data(API_CONFIG)
    # print(run_conf[PROJECT_NAME])
    # print(PROJECT_NAME)
    if run_conf:
        if PROJECT_NAME not in run_conf:
            run_conf[PROJECT_NAME][run_evn] = proj_conf
            # print(proj_conf)
            write_yaml_file(API_CONFIG, run_conf)
    else:
        api_conf = dict()
        api_conf[PROJECT_NAME][run_evn] = proj_conf
        write_yaml_file(API_CONFIG, api_conf)


def parse_request_parameter(har_ct):
    # 解析请求报文
    parameter = dict()
    method = har_ct["method"]
    try:
        if method in 'POST':
            parameter_list = urllib.parse.unquote(har_ct["request"]["body"]["text"])
        elif method in 'PUT':
            parameter_list = har_ct["request"]["body"]["text"]
        elif method in 'DELETE':
            parameter_list = urllib.parse.unquote(har_ct["request"]["body"]["text"])
        else:
            parameter_list = har_ct["query"]

        if parameter_list:
            if "&" in parameter_list:
                for key in parameter_list.split("&"):
                    val = key.split("=")
                    parameter[val[0]] = val[1]
            else:
                parameter = json.loads(parameter_list)
        else:
            parameter = None
        return parameter

    except Exception as e:
        logging.error("未找到parameter: %s" % e)
        raise e


def init_test_case(har_ct, module_path, parameter, file_name):
    # path = har_ct["path"]
    # title = path.split("/")[-1].replace('-', '')
    title = file_name
    # 定义测试用例
    test_case = dict()
    test_case["summary"] = title
    test_case["describe"] = 'test_' + title

    # 定义请求入参信息，且当参数字符总长度大于200时单独写入json文件
    if len(str(parameter)) > 200:
        param_name = title + '_request.json'
        if param_name not in os.listdir(module_path):
            # 定义请求json
            param_dict = dict()
            param_dict["summary"] = title
            param_dict["body"] = parameter
            param_file = module_path + '/' + param_name
            logging.info("生成请求文件: {}".format(param_file))
            write_json_file(param_file, [param_dict])
        test_case["parameter"] = param_name
    else:
        test_case["parameter"] = parameter

    # 定义请求返回信息
    response_code = har_ct["response"]["status"]
    response_body = har_ct["response"]["body"]["text"]
    check = dict()
    check["check_type"] = 'check_json_contain'
    check["expected_code"] = response_code
    expected_request = json.loads(response_body)

    # 当返回参数字符总长度大于200时单独写入json文件
    if len(str(expected_request)) > 200:
        result_name = title + '_response.json'
        if result_name not in os.listdir(module_path):
            # 定义响应json
            result_dict = dict()
            result_dict["summary"] = title
            result_dict["body"] = expected_request
            result_file = module_path + '/' + result_name
            logging.info("生成响应文件: {}".format(result_file))
            write_json_file(result_file, [result_dict])
        check["expected_result"] = result_name
    else:
        check["expected_result"] = expected_request
    test_case["check_body"] = check
    # print(test_case)
    return test_case


def write_case_yaml(har_path):
    """循环读取接口数据文件

    :param har_path: Charles导出文件路径
    :return:
    """
    case_file_list = list()
    logging.info("读取抓包文件主目录: {}".format(har_path))
    har_list = os.listdir(har_path)
    for each in har_list:
        # ext_name = os.path.splitext(each)[1]
        file_name, ext_name = os.path.splitext(each)
        if ext_name == '.chlsj':

            logging.info("读取抓包文件: {}".format(each))
            file_path = har_path + '/' + each
            with open(file_path, 'r', encoding='utf-8') as f:
                har_cts = json.loads(f.read())
                har_ct = har_cts[0]

                # 获取接口基本信息
                method = har_ct["method"]
                path = har_ct["path"]
                title = file_name
                # title = path.split("/")[-1].replace('-', '')
                module = path.split("/")[-2].replace('-', '')
                module_path = har_path.split('data')[0] + '/page/' + module

                # 创建模块目录
                try:
                    os.makedirs(module_path)
                except:
                    pass

                # 初始化api配置
                init_api_conf(har_ct)

                # 解析请求参数
                parameter = parse_request_parameter(har_ct)
                # print(har_ct)
                # print(module_path)
                # print(parameter)
                # print(file_name)

                # 初始化测试用例
                test_case = init_test_case(har_ct, module_path, parameter, file_name)

                # 定义测试信息
                test_info = dict()
                test_info["title"] = module
                test_info["host"] = '${host}'
                test_info["scheme"] = '${scheme}'
                test_info["method"] = method
                test_info["address"] = path
                test_info["mime_type"] = har_ct["request"]["mimeType"]
                test_info["headers"] = '${headers}'
                test_info["timeout"] = '${timeout}'
                test_info["file"] = False
                test_info["cookies"] = False
                test_info["premise"] = False

                # 合并测试信息、测试用例
                case_list = dict()
                case_list["test_info"] = test_info
                case_list["test_case"] = [test_case]

                # 写入测试用例(存在则忽略)
                case_name = 'test_' + title + '.yaml'
                case_file = module_path + '/' + case_name
                if not os.path.exists(case_file):
                    logging.info("生成用例文件: {}".format(case_file))
                    write_yaml_file(case_file, case_list)

                case_file_list.append(case_file)
    return case_file_list


def txt_change_yaml(har_path):
    """循环读取接口数据文件

    :param har_path: Charles导出文件路径
    :return:
    """
    har_path = har_path.split('page')[0]+'/data/'
    if num == None:
        count = 0
    elif num == 0:
        count = 0
    else:
        count = int(num) - 1
    case_file_list = list()
    logging.info("读取抓包文件主目录: {}".format(har_path))
    har_list = os.listdir(har_path)
    for each in har_list:
        # ext_name = os.path.splitext(each)[1]
        file_name, ext_name = os.path.splitext(each)
        if ext_name == '.chlsj':
            logging.info("读取抓包文件: {}".format(each))
            file_path = har_path + '/' + each
            with open(file_path, 'r', encoding='utf-8') as f:
                har_cts = json.loads(f.read())
                har_ct = har_cts[0]

                # 获取接口基本信息
                method = har_ct["method"]
                path = har_ct["path"]
                title = file_name
                # title = path.split("/")[-1].replace('-', '')
                module = path.split("/")[-2].replace('-', '')
                module_path = har_path.split('data')[0] + '/page/' + module

                # 创建模块目录
                try:
                    os.makedirs(module_path)
                except:
                    pass

                # 初始化api配置
                init_api_conf(har_ct)

                # 解析请求参数
                parameter = parse_request_parameter(har_ct)

                # 初始化测试用例
                test_case = init_test_case(har_ct, module_path, parameter, file_name)

                # 定义测试信息
                test_info = dict()
                test_info["title"] = module
                test_info["host"] = '${host}'
                test_info["scheme"] = '${scheme}'
                test_info["method"] = method
                test_info["address"] = path
                test_info["mime_type"] = har_ct["request"]["mimeType"]
                test_info["headers"] = '${headers}'
                test_info["timeout"] = '${timeout}'
                test_info["file"] = False
                test_info["cookies"] = False
                test_info["premise"] = False

                # 合并测试信息、测试用例
                case_list = dict()
                case_list["test_info"] = test_info
                case_list["test_case"] = [test_case]

                # 写入测试用例(存在则忽略)
                case_name = 'test_' + title + '.yaml'
                case_file = module_path + '/' + case_name
                if not os.path.exists(case_file):
                    logging.info("生成用例文件: {}".format(case_file))
                    write_yaml_file(case_file, case_list)

                case_file_list.append(case_file)
        elif ext_name == '.txt':
            headers = dict()
            check = dict()
            test_info = dict()
            case_list = dict()
            title = file_name
            module_path = har_path.split('data')[0] + '/page/' + title
            # 创建模块目录
            try:
                os.makedirs(module_path)
            except:
                pass

            logging.info("读取抓包文件主目录: {}".format(har_path))
            file_path = har_path + '/' + each
            fileObj = []
            filedata = open(file_path, encoding='utf-8').read()
            if '------------------------------------------------------------------' in filedata:
                fileObj = open(file_path, encoding='utf-8').read().split(
                    '------------------------------------------------------------------')
            else:
                fileObj.append(filedata+"\n\n")
                # print(type(filedata), fileObj)
            res = {}
            for linedata in fileObj:
                if 'HTTP/1.1' in linedata and linedata:
                    url, request, response = linedata.split('HTTP/1.1')
                    # 定义测试信息
                    test_info["host"] = '${host}'
                    test_info["scheme"] = '${scheme}'
                    test_info["headers"] = '${headers}'
                    test_info["timeout"] = '${timeout}'
                    test_info["file"] = False
                    test_info["cookies"] = False
                    test_info["premise"] = False
                    test_info["postposition"] = False

                    method, http = url.split()

                    scheme = http.split(':')[0]
                    host = http.split('/')[2]

                    proj_conf = dict()
                    proj_conf['timeout'] = 10
                    proj_conf['scheme'] = scheme
                    proj_conf['host'] = host
                    # 检查是否已存在项目配置信息，没有则写入
                    run_conf = read_yaml_data(API_CONFIG)
                    # print(run_conf[PROJECT_NAME])
                    # print(PROJECT_NAME)

                    test_info["method"] = method
                    sh, address = http.split('.cn',1)
                    test_info["address"] = address
                    if '?' not in http:
                        cl = url.split('/')[-2].replace('-', '_')
                        fun = url.split('/')[-1].replace('-', '_').split()[0]
                        name = cl + '_' + fun
                        # print(name)
                        # module_path = har_path.split('data')[0] + '/page/' + module
                    else:
                        cl = url.split('/')[-2].replace('-', '_')
                        fun = url.split('/')[-1].split('?')[0].replace('-', '_').split()[0]
                        if '&' in fun:
                            fun = fun.split('&')[0]
                        name = cl + '_' + fun
                        # print(name)

                    # 处理请求参数
                    item = request.split('\n')
                    parameter = {}
                    if method == 'POST':
                        if item[-2] != '':
                            try:
                                # 获取请求参数
                                p = urllib.parse.unquote(item[-2])
                                parameter = json.loads(p)
                            except JSONDecodeError:
                                par = item[-2].split('&')
                                for i in range(len(par)):
                                    key, value = par[i].split('=')
                                    parameter[key] = urllib.parse.unquote(value)
                        else:
                            parameter = {}
                    if method == 'GET':
                        if '?' in http:
                            test_info["address"] = address.split('?')[0]
                            # par = urllib.parse.quote(http.split('?')[1])
                            par = http.split('?')[1].split('&')
                            for i in range(len(par)):
                                key, value = par[i].split('=')
                                parameter[key] = value
                        else:
                            parameter = {}
                    # 去重
                    url1 = url.lstrip('\n')
                    if url1 in res.keys() and parameter in res.values():
                        continue
                    res[url1] = parameter
                    for par in item:
                        if ':' in par and par != item[-2]:
                            key, value = par.split(':', 1)
                            # 去除基础请求头
                            base_header = ['Host',
                                           'Content-Length',
                                           'User-Agent',
                                           'Origin',
                                           'Referer',
                                           'Connection',
                                           'Accept',
                                           'Accept-Encoding',
                                           'Trace-Id',
                                           'Cookie',
                                           'Accept-Language']

                            if key not in base_header:
                                header = "{'" + key + "': " + json.dumps(value.lstrip()) + "}"
                                headers.update(eval(header))
                            if 'Content-Type' in par:
                                test_info["mime_type"] = value
                            else:
                                test_info["mime_type"] = 'application/json'
                    # 判断是否存在自定义消息头
                    if headers:
                        proj_conf['headers'] = headers
                    else:
                        proj_conf['headers'] = None

                    if run_conf:
                        if PROJECT_NAME not in run_conf:
                            run_conf[PROJECT_NAME][run_evn] = proj_conf
                            write_yaml_file(API_CONFIG, run_conf)
                    else:
                        api_conf = dict()
                        api_conf[PROJECT_NAME][run_evn] = proj_conf
                        write_yaml_file(API_CONFIG, api_conf)
                    # count += 1
                    # case_name = 'test_0' + str(count) + "_" + name + '.yaml'
                    count += 1
                    if count < 10:
                        case_name = 'test_00' + str(count) + "_" + name + '.yaml'
                    elif 10 <= count < 100:
                        case_name = 'test_0' + str(count) + "_" + name + '.yaml'
                    else:
                        case_name = 'test_' + str(count) + "_" + name + '.yaml'
                    test_info["title"] = case_name.split('.')[0]
                    # 合并测试信息、测试用例
                    case_list["test_info"] = test_info

                    # 处理返回参数
                    resp = response.split('\n')
                    code = resp[0].split()[0]
                    check["expected_code"] = int(code)
                    # if resp[-3] == {}:
                    #     check["check_type"] = 'check_string'

                    # else:
                    check["check_type"] = 'check_json_contain'
                    if resp[-3] != '':
                        expected_request = resp[-3]
                        print("expected_request :",expected_request)
                        check["expected_result"] = json.loads(expected_request)
                    else:
                        check["expected_result"] = {}

                    # 定义测试用例
                    test_case = dict()
                    test_case["summary"] = case_name.split('.')[0][6:]
                    test_case["describe"] = case_name.split('.')[0]
                    test_case["parameter"] = parameter
                    test_case["check_body"] = check
                    case_list["test_case"] = [test_case]
                    # 写入测试用例(存在则忽略)
                    case_file = module_path + '/' + case_name
                    # print(case_list)
                    if not os.path.exists(case_file):
                        logging.info("生成用例文件: {}".format(case_file))
                        write_yaml_file(case_file, case_list)

                    case_file_list.append(case_file)

        elif ext_name == '.json':
            headers = {}
            proj_conf = {'timeout': 10, 'scheme': 'https', 'host': 'test-design.myscrm.cn',
                         'headers': {'orgcode': '"gzminjieadmin_test"', 'subject_id': '"phbvik1545297516"',
                                     'Content-Type': '"application/json; charset=utf-8"'}}

            case_list = {'test_info': {'host': '${host}', 'scheme': '${scheme}', 'headers': '${headers}',
                                       'timeout': '${timeout}',
                                       'file': False, 'cookies': False, 'premise': False, 'postposition': False,
                                       'method': 'POST',
                                       'address': '/bff-coc-h5/v1/material-center/save',
                                       'mime_type': 'application/json',
                                       'title': 'test_001_material_center_save.yaml'}, 'test_case': [
                {'summary': 'save', 'describe': 'test_save',
                 'parameter': {},
                 'check_body': {
                     'check_type': 'check_json_contain',
                     'expected_code': 200,
                     'expected_result': {}
                 }
                 }
            ]}
            test_info = case_list.get('test_info')
            dir = file_name.split('.postman')[0]
            module_path = har_path.split('data')[0] + '/page/' + dir
            # 创建模块目录
            try:
                os.makedirs(module_path)
            except:
                pass
            logging.info("读取抓包文件主目录: {}".format(har_path))
            file_path = har_path + '/' + each
            data = read_json_data(file_path).get('item')
            for j in data:
                case = list()
                data_list = dispose_postman(j, case)
                for i in data_list:
                    request = i.get('request')
                    method = request.get('method')
                    test_info["method"] = method
                    address = request.get('url').get('raw').split('.cn')[1]
                    if '?' in address:
                        address = address.split('?')[0]
                    if '?' in address:
                        summary = address.split('/')[-2] + '_' + address.split('/')[-1].split('?')[0]
                    else:
                        summary = address.split('/')[-2] + '_' + address.split('/')[-1]
                    count += 1
                    summary = summary.replace('-', '_')
                    if count < 10:
                        case_name = 'test_00' + str(count) + '_' + summary + '.yaml'
                    elif 10 <= count < 100:
                        case_name = 'test_0' + str(count) + '_' + summary + '.yaml'
                    else:
                        case_name = 'test_' + str(count) + '_' + summary + '.yaml'
                    case_list['test_case'][0]['summary'] = case_name.split('.')[0][6:]
                    case_list['test_case'][0]['describe'] = case_name.split('.')[0]
                    case_list['test_info']['title'] = case_name.split('.')[0]
                    test_info["address"] = address
                    key = request.get('header')[0].get('key')
                    value = request.get('header')[0].get('value')
                    headers[key] = value
                    proj_conf['headers'] = headers
                    if method == 'GET':
                        if 'body' in request.keys():
                            parameter = request.get('body').get('raw').replace('\n', '').replace('\r', '')
                            case_list["test_case"][0]["parameter"] = json.loads(parameter)
                        else:
                            if '://' in request.get('url').get('raw'):
                                scheme, host = request.get('url').get('raw').split('://')
                            else:
                                scheme = 'http'
                                host = request.get('url').get('raw')
                            host = host.split('.cn')[0] + '.cn'
                            proj_conf['scheme'] = scheme
                            proj_conf['host'] = host
                            case_list["test_case"][0]["parameter"] = {}
                    else:
                        if '://' in request.get('url').get('raw'):
                            scheme, host = request.get('url').get('raw').split('://')
                        else:
                            scheme = 'http'
                            host = request.get('url').get('raw')
                        proj_conf['scheme'] = scheme
                        host = host.split('.cn')[0] + '.cn'
                        proj_conf['host'] = host
                        # parameter = request.get('body').get('raw').replace('\n', '').replace('\r', '')
                        try:
                            parameter = request.get('body').get('raw').replace('\n', '').replace('\r', '')
                        except:
                            parameter = "{}"
                        case_list["test_case"][0]["parameter"] = json.loads(parameter)
                        mime_type = 'json'
                        if mime_type == 'json':
                            test_info["mime_type"] = 'application/json'
                        else:
                            test_info["mime_type"] = None
                    # 写入测试用例(存在则忽略)
                    case_file = module_path + '/' + case_name
                    case_list["test_case"][0]['check_body']["check_type"] = 'check_json_contain'
                    # print(case_list)
                    if not os.path.exists(case_file):
                        logging.info("生成用例文件: {}".format(case_file))
                        write_yaml_file(case_file, case_list)
                    case_file_list.append(case_file)
            # 检查是否已存在项目配置信息，没有则写入
            run_conf = read_yaml_data(API_CONFIG)
            if run_conf:
                if PROJECT_NAME not in run_conf:
                    run_conf[PROJECT_NAME][run_evn] = proj_conf
                    write_yaml_file(API_CONFIG, run_conf)
            else:
                api_conf = dict()
                api_conf[PROJECT_NAME][run_evn] = proj_conf
                write_yaml_file(API_CONFIG, api_conf)
        count = 0
    return case_file_list


def dispose_postman(data, case):
    if 'item' in data.keys():
        data = data.get('item')
        for i in data:
            dispose_postman(i, case)
        return case
    else:
        case.append(data)
        return case


if __name__ == '__main__':
    # real_path = os.path.dirname(os.path.realpath(__file__)).replace('\\', '/')
    real_path = "/Users/qiu/文档/ApiTesting-main/Coc".replace('\\', '/')
    print('测试用例列表: ', txt_change_yaml(real_path + '/data'))
